home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndhrdw / phoenix.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  14KB  |  633 lines

  1. /****************************************************************************
  2.  *
  3.  * Phoenix sound hardware simulation - still very ALPHA!
  4.  *
  5.  * If you find errors or have suggestions, please mail me.
  6.  * Juergen Buchmueller <pullmoll@t-online.de>
  7.  *
  8.  ****************************************************************************/
  9.  
  10.  
  11. #include <math.h>
  12. #include "driver.h"
  13.  
  14. /****************************************************************************
  15.  * 4006
  16.  * Dual 4-bit and dual 5-bit serial-in serial-out shift registers.
  17.  *
  18.  *            +----------+
  19.  *        1D5 |1    +--+ 14| VCC
  20.  *       /1Q4 |2         13| 1Q1
  21.  *        CLK |3         12| 2Q0
  22.  *        2D4 |4    4006 11| 2Q0
  23.  *        3D4 |5         10| 3Q0
  24.  *        4D5 |6          9| 4Q0
  25.  *        GND |7          8| 4Q1
  26.  *            +----------+
  27.  *
  28.  * [This information is part of the GIICM]
  29.  *
  30.  * Pin 8 and 9 are connected to an EXOR gate and the inverted
  31.  * output (EXNOR) is fed back to pin 1 (and the pseudo polynome output).
  32.  *
  33.  *        1D5          1Q1  2D4        2Q0  3D4       3Q0    4D5      4Q1 4Q0
  34.  *        +--+--+--+--+--+  +--+--+--+--+  +--+--+--+--+    +--+--+--+--+--+
  35.  *     +->| 0| 1| 2| 3| 4|->| 5| 6| 7| 8|->| 9|10|11|12|->|13|14|15|16|17|
  36.  *     |    +--+--+--+--+--+  +--+--+--+--+  +--+--+--+--+    +--+--+--+--+--+
  37.  *     |                                             ____              |  |
  38.  *     |                                            /     |------------+  |
  39.  *     +-----------------------------------------|EXNOR|                 |
  40.  *                                                \____|---------------+
  41.  *
  42.  ****************************************************************************/
  43.  
  44. #define VMIN    0
  45. #define VMAX    32767
  46.  
  47. static int sound_latch_a;
  48. static int sound_latch_b;
  49.  
  50. static int channel;
  51.  
  52. static int tone1_vco1_cap;
  53. static int tone1_level;
  54. static int tone2_level;
  55.  
  56. static UINT32 *poly18 = NULL;
  57.  
  58. INLINE int tone1_vco1(int samplerate)
  59. {
  60.     static int output, counter, level;
  61.     /*
  62.      * L447 (NE555): Ra=47k, Rb=100k, C = 0.01uF, 0.48uF, 1.01uF or 1.48uF
  63.      * charge times = 0.639*(Ra+Rb)*C = 0.0092s, 0.0451s, 0.0949s, 0.1390s
  64.      * discharge times = 0.639*Rb*C = 0.0064s, 0.0307s, 0.0645s, 0.0946s
  65.      */
  66.     #define C18a    0.01e-6
  67.     #define C18b    0.48e-6
  68.     #define C18c    1.01e-6
  69.     #define C18d    1.48e-6
  70.     #define R40     47000
  71.     #define R41     100000
  72.     static int rate[2][4] = {
  73.         {
  74.             VMAX*2/3/(0.693*(R40+R41)*C18a),
  75.             VMAX*2/3/(0.693*(R40+R41)*C18b),
  76.             VMAX*2/3/(0.693*(R40+R41)*C18c),
  77.             VMAX*2/3/(0.693*(R40+R41)*C18d)
  78.         },
  79.         {
  80.             VMAX*2/3/(0.693*R41*C18a),
  81.             VMAX*2/3/(0.693*R41*C18b),
  82.             VMAX*2/3/(0.693*R41*C18c),
  83.             VMAX*2/3/(0.693*R41*C18d)
  84.         }
  85.     };
  86.     if( output )
  87.     {
  88.         if (level > VMAX*1/3)
  89.         {
  90.             counter -= rate[1][tone1_vco1_cap];
  91.             if( counter <= 0 )
  92.             {
  93.                 int steps = -counter / samplerate + 1;
  94.                 counter += steps * samplerate;
  95.                 if( (level -= steps) <= VMAX*1/3 )
  96.                 {
  97.                     level = VMAX*1/3;
  98.                     output = 0;
  99.                 }
  100.             }
  101.         }
  102.     }
  103.     else
  104.     {
  105.         if (level < VMAX*2/3)
  106.         {
  107.             counter -= rate[0][tone1_vco1_cap];
  108.             if( counter <= 0 )
  109.             {
  110.                 int steps = -counter / samplerate + 1;
  111.                 counter += steps * samplerate;
  112.                 if( (level += steps) >= VMAX*2/3 )
  113.                 {
  114.                     level = VMAX*2/3;
  115.                     output = 1;
  116.                 }
  117.             }
  118.         }
  119.     }
  120.     return output;
  121. }
  122.  
  123. INLINE int tone1_vco2(int samplerate)
  124. {
  125.     static int output, counter, level;
  126.  
  127.     /*
  128.      * L517 (NE555): Ra=570k, Rb=570k, C=10uF
  129.      * charge time = 0.639*(Ra+Rb)*C = 7.9002s
  130.      * discharge time = 0.639*Rb*C = 3.9501s
  131.      */
  132.     #define C20 10.0e-6
  133.     #define R43 570000
  134.     #define R44 570000
  135.  
  136.     if( output )
  137.     {
  138.         if (level > VMIN)
  139.         {
  140.             counter -= (int)(VMAX*2/3 / (0.693 * R44 * C20));
  141.             if( counter <= 0 )
  142.             {
  143.                 int steps = -counter / samplerate + 1;
  144.                 counter += steps * samplerate;
  145.                 if( (level -= steps) <= VMAX*1/3 )
  146.                 {
  147.                     level = VMAX*1/3;
  148.                     output = 0;
  149.                 }
  150.             }
  151.         }
  152.     }
  153.     else
  154.     {
  155.         if (level < VMAX)
  156.         {
  157.             counter -= (int)(VMAX*2/3 / (0.693 * (R43 + R44) * C20));
  158.             if( counter <= 0 )
  159.             {
  160.                 int steps = -counter / samplerate + 1;
  161.                 counter += steps * samplerate;
  162.                 if( (level += steps) >= VMAX*2/3 )
  163.                 {
  164.                     level = VMAX*2/3;
  165.                     output = 1;
  166.                 }
  167.             }
  168.         }
  169.     }
  170.  
  171.     return output;
  172. }
  173.  
  174. INLINE int tone1_vco(int samplerate, int vco1, int vco2)
  175. {
  176.     static int counter, level, rate, charge;
  177.     int voltage;
  178.  
  179.     if (level != charge)
  180.     {
  181.         /* charge or discharge C22 */
  182.         counter -= rate;
  183.         while( counter <= 0 )
  184.         {
  185.             counter += samplerate;
  186.             if( level < charge )
  187.             {
  188.                 if( ++level == charge )
  189.                     break;
  190.             }
  191.             else
  192.             {
  193.                 if( --level == charge )
  194.                     break;
  195.             }
  196.         }
  197.     }
  198.  
  199.     if( vco2 )
  200.     {
  201.         #define C22 100.0e-6
  202.         #define R42 10000
  203.         #define R45 51000
  204.         #define R46 51000
  205.         #define RP    27777    /* R42+R46 parallel with R45 */
  206.         if( vco1 )
  207.         {
  208.             /*        R42 10k
  209.              * +5V -/\/\/------------+
  210.              *               5V         |
  211.              * +5V -/\/\/--+--/\/\/--+--> V/C
  212.              *       R45 51k | R46 51k
  213.              *              ---
  214.              *              --- 100u
  215.              *               |
  216.              *              0V
  217.              */
  218.             charge = VMAX;
  219.             rate = (int)((charge - level) / (RP * C22));
  220.             voltage = level + (VMAX-level) * R46 / (R46 + R42);
  221.         }
  222.         else
  223.         {
  224.             /*        R42 10k
  225.              *    0V -/\/\/------------+
  226.              *              2.7V         |
  227.              * +5V -/\/\/--+--/\/\/--+--> V/C
  228.              *       R45 51k | R46 51k
  229.              *              ---
  230.              *              --- 100u
  231.              *               |
  232.              *              0V
  233.              */
  234.             /* simplification: charge = (R42 + R46) / (R42 + R45 + R46); */
  235.             charge = VMAX * 27 / 50;
  236.             if (charge >= level)
  237.                 rate = (int)((charge - level) / (R45 * C22));
  238.             else
  239.                 rate = (int)((level - charge) / ((R46+R42) * C22));
  240.             voltage = level * R42 / (R46 + R42);
  241.         }
  242.     }
  243.     else
  244.     {
  245.         if( vco1 )
  246.         {
  247.             /*        R42 10k
  248.              * +5V -/\/\/------------+
  249.              *              2.3V         |
  250.              *    0V -/\/\/--+--/\/\/--+--> V/C
  251.              *       R45 51k | R46 51k
  252.              *              ---
  253.              *              --- 100u
  254.              *               |
  255.              *              0V
  256.              */
  257.             /* simplification: charge = VMAX * R45 / (R42 + R45 + R46); */
  258.             charge = VMAX * 23 / 50;
  259.             if (charge >= level)
  260.                 rate = (int)((charge - level) / ((R42 + R46) * C22));
  261.             else
  262.                 rate = (int)((level - charge) / (R45 * C22));
  263.             voltage = level + (VMAX - level) * R46 / (R42 + R46);
  264.         }
  265.         else
  266.         {
  267.             /*        R42 10k
  268.              *    0V -/\/\/------------+
  269.              *               0V         |
  270.              *    0V -/\/\/--+--/\/\/--+--> V/C
  271.              *       R45 51k | R46 51k
  272.              *              ---
  273.              *              --- 100u
  274.              *               |
  275.              *              0V
  276.              */
  277.             charge = VMIN;
  278.             rate = (int)((level - charge) / (RP * C22));
  279.             voltage = level * R42 / (R46 + R42);
  280.         }
  281.     }
  282.  
  283.     /* L507 (NE555): Ra=20k, Rb=20k, C=0.001uF
  284.      * frequency 1.44/((Ra+2*Rb)*C) = 24kHz
  285.      */
  286.     return 24000*1/3 + 24000*2/3 * voltage / 32768;
  287. }
  288.  
  289. INLINE int tone1(int samplerate)
  290. {
  291.     static int counter, divisor, output;
  292.     int vco1 = tone1_vco1(samplerate);
  293.     int vco2 = tone1_vco2(samplerate);
  294.     int frequency = tone1_vco(samplerate, vco1, vco2);
  295.  
  296.     if( (sound_latch_a & 15) != 15 )
  297.     {
  298.         counter -= frequency;
  299.         while( counter <= 0 )
  300.         {
  301.             counter += samplerate;
  302.             if( ++divisor == 16 )
  303.             {
  304.                 divisor = sound_latch_a & 15;
  305.                 output ^= 1;
  306.             }
  307.         }
  308.     }
  309.  
  310.     return output ? tone1_level : -tone1_level;
  311. }
  312.  
  313. INLINE int tone2_vco(int samplerate)
  314. {
  315.     static int counter, level;
  316.  
  317.     /*
  318.      * This is how the tone2 part of the circuit looks like.
  319.      * I was having a hard time to guesstimate the results
  320.      * and they might still be wrong :(
  321.      *
  322.      *                            +12V
  323.      *                             |
  324.      *                             / R23
  325.      *                             \ 100k
  326.      *                             /
  327.      * !bit4    | /|    R22      |
  328.      * 0V/5V >--|< |---/\/\/-----+-------+---> V C7
  329.      *            | \|    47k      |         |
  330.      *            D4                 |        _|_
  331.      *                       6.8u ---     \ / D5
  332.      *                       C7    ---     ---
  333.      *                             |         |
  334.      *                             |         |
  335.      *      0V >-------------------+-/\/\/-+
  336.      *                             R24 33k
  337.      *
  338.      * V C7 min:
  339.      * 0.7V + (12V - 0.7V) * 19388 / (100000 + 19388) = 2.54V
  340.      * V C7 max:
  341.      * 0.7V + (12V - 0.7V) * 33000 / (100000 + 33000) +
  342.      *          (12V - 5.7V) * 47000 / (100000 + 47000) = 5.51V
  343.      */
  344.  
  345.     #define C7  6.8e-6
  346.     #define R23 100000
  347.     #define R22 47000
  348.     #define R24 33000
  349.     #define R22pR24 19388
  350.  
  351.     #define C7_MIN (VMAX * 254 / 500)
  352.     #define C7_MAX (VMAX * 551 / 500)
  353.     #define C7_DIFF (C7_MAX - C7_MIN)
  354.  
  355.     if( (sound_latch_b & 0x10) == 0 )
  356.     {
  357.         counter -= (C7_MAX - level) * 12 / (R23 * C7) / 5;
  358.         if( counter <= 0 )
  359.         {
  360.             int n = (-counter / samplerate) + 1;
  361.             counter += n * samplerate;
  362.             if( (level += n) > C7_MAX)
  363.                 level = C7_MAX;
  364.         }
  365.     }
  366.     else
  367.     {
  368.         counter -= (level - C7_MIN) * 12 / (R22pR24 * C7) / 5;
  369.         if( counter <= 0 )
  370.         {
  371.             int n = (-counter / samplerate) + 1;
  372.             counter += n * samplerate;
  373.             if( (level -= n) < C7_MIN)
  374.                 level = C7_MIN;
  375.         }
  376.     }
  377.     /*
  378.      * L487 (NE555):
  379.      * Ra = R25 (47k), Rb = R26 (47k), C = C8 (0.001uF)
  380.      * frequency 1.44/((Ra+2*Rb)*C) = 10212 Hz
  381.      */
  382.     return 10212 * level / 32768;
  383. }
  384.  
  385. INLINE int tone2(int samplerate)
  386. {
  387.     static int counter, divisor, output;
  388.     int frequency = tone2_vco(samplerate);
  389.  
  390.     if( (sound_latch_b & 15) != 15 )
  391.     {
  392.         counter -= frequency;
  393.         while( counter <= 0 )
  394.         {
  395.             counter += samplerate;
  396.             if( ++divisor == 16 )
  397.             {
  398.                 divisor = sound_latch_b & 15;
  399.                 output ^= 1;
  400.             }
  401.         }
  402.     }
  403.     return output ? tone2_level : -tone2_level;
  404. }
  405.  
  406. INLINE int update_c24(int samplerate)
  407. {
  408.     static int counter, level;
  409.     /*
  410.      * Noise frequency control (Port B):
  411.      * Bit 6 lo charges C24 (6.8u) via R51 (330) and when
  412.      * bit 6 is hi, C24 is discharged through R52 (20k)
  413.      * in approx. 20000 * 6.8e-6 = 0.136 seconds
  414.      */
  415.     #define C24 6.8e-6
  416.     #define R49 1000
  417.     #define R51 330
  418.     #define R52 20000
  419.     if( sound_latch_a & 0x40 )
  420.     {
  421.         if (level > VMIN)
  422.         {
  423.             counter -= (int)((level - VMIN) / (R52 * C24));
  424.             if( counter <= 0 )
  425.             {
  426.                 int n = -counter / samplerate + 1;
  427.                 counter += n * samplerate;
  428.                 if( (level -= n) < VMIN)
  429.                     level = VMIN;
  430.             }
  431.         }
  432.     }
  433.     else
  434.     {
  435.         if (level < VMAX)
  436.         {
  437.             counter -= (int)((VMAX - level) / ((R51+R49) * C24));
  438.             if( counter <= 0 )
  439.             {
  440.                 int n = -counter / samplerate + 1;
  441.                 counter += n * samplerate;
  442.                 if( (level += n) > VMAX)
  443.                     level = VMAX;
  444.             }
  445.         }
  446.     }
  447.     return VMAX - level;
  448. }
  449.  
  450. INLINE int update_c25(int samplerate)
  451. {
  452.     static int counter, level;
  453.     /*
  454.      * Bit 7 hi charges C25 (6.8u) over a R50 (1k) and R53 (330) and when
  455.      * bit 7 is lo, C25 is discharged through R54 (47k)
  456.      * in about 47000 * 6.8e-6 = 0.3196 seconds
  457.      */
  458.     #define C25 6.8e-6
  459.     #define R50 1000
  460.     #define R53 330
  461.     #define R54 47000
  462.  
  463.     if( sound_latch_a & 0x80 )
  464.     {
  465.         if (level < VMAX)
  466.         {
  467.             counter -= (int)((VMAX - level) / ((R50+R53) * C25));
  468.             if( counter <= 0 )
  469.             {
  470.                 int n = -counter / samplerate + 1;
  471.                 counter += n * samplerate;
  472.                 if( (level += n) > VMAX )
  473.                     level = VMAX;
  474.             }
  475.         }
  476.     }
  477.     else
  478.     {
  479.         if (level > VMIN)
  480.         {
  481.             counter -= (int)((level - VMIN) / (R54 * C25));
  482.             if( counter <= 0 )
  483.             {
  484.                 int n = -counter / samplerate + 1;
  485.                 counter += n * samplerate;
  486.                 if( (level -= n) < VMIN )
  487.                     level = VMIN;
  488.             }
  489.         }
  490.     }
  491.     return level;
  492. }
  493.  
  494.  
  495. INLINE int noise(int samplerate)
  496. {
  497.     static int counter, polyoffs, polybit, lowpass_counter, lowpass_polybit;
  498.     int vc24 = update_c24(samplerate);
  499.     int vc25 = update_c25(samplerate);
  500.     int sum = 0, level, frequency;
  501.  
  502.     /*
  503.      * The voltage levels are added and control I(CE) of transistor TR1
  504.      * (NPN) which then controls the noise clock frequency (linearily?).
  505.      * level = voltage at the output of the op-amp controlling the noise rate.
  506.      */
  507.     if( vc24 < vc25 )
  508.         level = vc24 + (vc25 - vc24) / 2;
  509.     else
  510.         level = vc25 + (vc24 - vc25) / 2;
  511.  
  512.     frequency = 588 + 6325 * level / 32768;
  513.  
  514.     /*
  515.      * NE555: Ra=47k, Rb=1k, C=0.05uF
  516.      * minfreq = 1.44 / ((47000+2*1000) * 0.05e-6) = approx. 588 Hz
  517.      * R71 (2700 Ohms) parallel to R73 (47k Ohms) = approx. 2553 Ohms
  518.      * maxfreq = 1.44 / ((2553+2*1000) * 0.05e-6) = approx. 6325 Hz
  519.      */
  520.     counter -= frequency;
  521.     if( counter <= 0 )
  522.     {
  523.         int n = (-counter / samplerate) + 1;
  524.         counter += n * samplerate;
  525.         polyoffs = (polyoffs + n) & 0x3ffff;
  526.         polybit = (poly18[polyoffs>>5] >> (polyoffs & 31)) & 1;
  527.     }
  528.     if (!polybit)
  529.         sum += vc24;
  530.  
  531.     /* 400Hz crude low pass filter: this is only a guess!! */
  532.     lowpass_counter -= 400;
  533.     if( lowpass_counter <= 0 )
  534.     {
  535.         lowpass_counter += samplerate;
  536.         lowpass_polybit = polybit;
  537.     }
  538.     if (!lowpass_polybit)
  539.         sum += vc25;
  540.  
  541.     return sum;
  542. }
  543.  
  544. static void phoenix_sound_update(int param, INT16 *buffer, int length)
  545. {
  546.     int samplerate = Machine->sample_rate;
  547.  
  548.     while( length-- > 0 )
  549.     {
  550.         int sum = 0;
  551.         sum = (tone1(samplerate) + tone2(samplerate) + noise(samplerate)) / 4;
  552.         *buffer++ = sum < 32768 ? sum > -32768 ? sum : -32768 : 32767;
  553.     }
  554. }
  555.  
  556. WRITE_HANDLER( phoenix_sound_control_a_w )
  557. {
  558.     if( data == sound_latch_a )
  559.         return;
  560.  
  561.     stream_update(channel,0);
  562.     sound_latch_a = data;
  563.  
  564.     tone1_vco1_cap = (sound_latch_a >> 4) & 3;
  565.     if( sound_latch_a & 0x20 )
  566.         tone1_level = VMAX * 10000 / (10000+10000);
  567.     else
  568.         tone1_level = VMAX;
  569. }
  570.  
  571. WRITE_HANDLER( phoenix_sound_control_b_w )
  572. {
  573.     if( data == sound_latch_b )
  574.         return;
  575.  
  576.     stream_update(channel,0);
  577.     sound_latch_b = data;
  578.  
  579.     if( sound_latch_b & 0x20 )
  580.         tone2_level = VMAX * 10 / 11;
  581.     else
  582.         tone2_level = VMAX;
  583.  
  584.     /* eventually change the tune that the MM6221AA is playing */
  585.     mm6221aa_tune_w(0, sound_latch_b >> 6);
  586. }
  587.  
  588. int phoenix_sh_start(const struct MachineSound *msound)
  589. {
  590.     int i, j;
  591.     UINT32 shiftreg;
  592.  
  593.     poly18 = (UINT32 *)malloc((1ul << (18-5)) * sizeof(UINT32));
  594.  
  595.     if( !poly18 )
  596.         return 1;
  597.  
  598.     shiftreg = 0;
  599.     for( i = 0; i < (1ul << (18-5)); i++ )
  600.     {
  601.         UINT32 bits = 0;
  602.         for( j = 0; j < 32; j++ )
  603.         {
  604.             bits = (bits >> 1) | (shiftreg << 31);
  605.             if( ((shiftreg >> 16) & 1) == ((shiftreg >> 17) & 1) )
  606.                 shiftreg = (shiftreg << 1) | 1;
  607.             else
  608.                 shiftreg <<= 1;
  609.         }
  610.         poly18[i] = bits;
  611.     }
  612.  
  613.     channel = stream_init("Custom", 50, Machine->sample_rate, 0, phoenix_sound_update);
  614.     if( channel == -1 )
  615.         return 1;
  616.  
  617.     return 0;
  618. }
  619.  
  620. void phoenix_sh_stop(void)
  621. {
  622.     if( poly18 )
  623.         free(poly18);
  624.     poly18 = NULL;
  625. }
  626.  
  627. void phoenix_sh_update(void)
  628. {
  629.     stream_update(channel, 0);
  630. }
  631.  
  632.  
  633.